#include "socket.h"
#include "inet_address.h"


Socket::Socket()
: sockfd_(invalid_socket)
, address_(nullptr) {
}

Socket::Socket(socket_type sockfd, InetAddress* address)
: sockfd_(sockfd)
, address_(address)
, isConnect_(true) {
    assert(sockfd > 0 && address != nullptr);
}

bool Socket::connect(InetAddress* address) {
    assert(address != nullptr);
    address_ = address;
    sockfd_ = ::socket(address->family(), SOCK_STREAM, IPPROTO_TCP);
    assert(sockfd_ != invalid_socket);
    return ::connect(sockfd_, address_->addr(), sizeof(sockaddr_type)) == 0;
}

void Socket::disconnect() {
    if(isConnect()) {
#ifdef _WIN32
        ::closesocket(sockfd_);
#elif __linux__
        ::close(sockfd_);
#endif
    }
}

bool Socket::isConnect() const {
    return sockfd_ > 0 && isConnect_;
}


int Socket::write(const char* buf, int len) {
    assert(isConnect());
    return ::send(sockfd_, buf, len, 0);
}

int Socket::write(const std::vector<char>& buf) {
    return write(buf.data(), buf.size());
}

int Socket::write(const std::string& buf) {
    return write(buf.c_str(), buf.size());
}

std::vector<char> Socket::read(int size) {
    assert(isConnect());
    std::vector<char> buf(size);
    int len = ::recv(sockfd_, buf.data(), buf.size(), 0);
    if(len <= 0) {
        buf.clear();
    } else {
        buf.resize(len);
    }
    return std::move(buf);
}

std::vector<char> Socket::readAll() {
    return read(4096);
}

InetAddress* Socket::address() {
    return this->address_;
}

socket_type Socket::sockfd() const {
    return sockfd_;
}
